#!/usr/bin/env python
# encoding: utf-8
# author: 04


import datetime

from django.db import close_old_connections

from main import _script_head  # noqa
from main import config
from main.common.audit_queue import PurifyQueue, WebQueue
from main.common.constants import (PURIFY_ACTIVE_TIME_EXPIRE,
                                   WEB_ACTIVE_TIME_EXPIRE)
from main.common.redis.redis_cli import RedisClient
from main.service.base import BaseService


class _FakeUser(object):
    def __init__(self, username):
        self.username = username


class FakeUser(object):
    def __init__(self, username, uid):
        self.id = uid
        self.name = username
        self.user = _FakeUser(username)


class PurifyCheckData(BaseService):
    """  active_time 来源： 每次用户答题之后更新
    当 active_time 一定时长未更新，认为是超时，清空队列
    """

    loop_sep = 30
    lock_multi_duration = 3
    conflict_key = 'PurifyCheckData'

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.client = RedisClient
        self.scan_count = 10000    # 单次扫描上限，可根据性能情况调整
        self.timeout_seconds = PURIFY_ACTIVE_TIME_EXPIRE

    def task(self):
        """ 数据检查
        1. 清理3.5分钟未答题的所有缓存队列
        """
        close_old_connections()  # https://www.jianshu.com/p/d2ba42feee15  避免长时间运行之后出现 MySQL server has gone away

        self.clean_app_user_queue()
        self.clean_web_user_queue()

    def clean_app_user_queue(self):
        """
        """
        self.clean_user_queue(PurifyQueue, PURIFY_ACTIVE_TIME_EXPIRE)

    def clean_web_user_queue(self):
        self.clean_user_queue(WebQueue, WEB_ACTIVE_TIME_EXPIRE if config.ENV.startswith('pro') else 60)

    def clean_user_queue(self, queue_class, timeout_seconds):
        cursor_point = 0
        match_pattern = f'{queue_class.prefix}_meta:*'
        while True:
            cursor_point, redis_key_list = self.client.scan(
                cursor=cursor_point, match=match_pattern, count=self.scan_count)
            self.scan_meta(redis_key_list, timeout_seconds, queue_class)
            if cursor_point == 0:
                break

    def scan_meta(self, redis_key_list, timeout_seconds, queue_class):
        """ 检查传入的各key，meta值是否超时
        """
        now = datetime.datetime.now()
        pipe = self.client.pipeline()
        for key in redis_key_list:
            pipe.hget(key, 'active_time')
        all_data = pipe.execute()
        for key, timestamp in zip(redis_key_list, all_data):
            if timestamp is not None:
                active_time = datetime.datetime.fromtimestamp(int(timestamp))
                if (now - active_time).total_seconds() < timeout_seconds:
                    # 合法数据
                    continue
            # 无timestamp或超时，清除数据
            self.clear_cache(key, queue_class)

    def clear_cache(self, key, queue_class):
        """ 清空当前cache
        """
        res = key.decode().split(':')
        uname, uid = res[1], res[2]
        purify_config_id = ''
        if len(res) > 3:
            purify_config_id = res[3]
        self.logger.info(f'CheckData<expire>: {queue_class.__name__} data for {uname}:{uid} cleared')
        user = FakeUser(uname, uid)
        print(dir(user))
        purify_queue = queue_class(user, purify_config_id=purify_config_id)
        purify_queue.clear_cache()


if __name__ == "__main__":
    PurifyCheckData().run()
